/*
	Copyright (c) 2010 <copyright holders>
	This source code is licensed under The MIT License,
	see the file LICENSE for details.
	*/

#include "UnitInvariant.hpp"

#include <boost/property_tree/info_parser.hpp>
#include <boost/property_tree/ptree.hpp>

namespace spelprog2 {
namespace sim {

ProjectileInvariant::ProjectileInvariant(const boost::property_tree::ptree & projectileNode)
{
    Name_           = projectileNode.get<std::string>("name");
    Animation_      = projectileNode.get<std::string>("animation");

    MeshName_       = projectileNode.get<std::string>("mesh.name");
    MeshYaw_        = projectileNode.get<float>("mesh.yaw") / 180.0f * FLOAT_PI;
    MeshScale_      = projectileNode.get<float>("mesh.scale");

    LaunchSpeed_    = projectileNode.get<WideInt>("launch_speed");
}

Attack::Attack(const boost::property_tree::ptree & attackNode) :
    projectile_()
{
    using namespace boost::property_tree;

    Name_               = attackNode.get<std::string>("name");
    Animation_          = attackNode.get<std::string>("animation");

    TotalTime_          = attackNode.get<WideInt>("timing.total_time");
    EffectTime_         = attackNode.get<WideInt>("timing.effect_time");
    RelativeFrequency_  = attackNode.get<WideInt>("timing.relative_frequency");

    ArcWidth_           = Int(attackNode.get<WideInt>("arc.width")) * ANGULAR_UNITS_PER_HALFCIRCLE / Int(180);
    ArcOrigin_          = Int(attackNode.get<WideInt>("arc.origin")) * ANGULAR_UNITS_PER_HALFCIRCLE / Int(180);
    Range_              = attackNode.get<WideInt>("arc.range");

    HealthDamageMin_    = attackNode.get<WideInt>("damage.health_min");
    HealthDamageMax_    = attackNode.get<WideInt>("damage.health_max");
    MoraleDamageMin_    = attackNode.get<WideInt>("damage.morale_min");
    MoraleDamageMax_    = attackNode.get<WideInt>("damage.morale_max");

    ptree::const_assoc_iterator it = attackNode.find("projectile");
    if (it != attackNode.not_found()) {
        projectile_ = ProjectileInvariant(it->second);
    }
}

UnitInvariant::UnitInvariant(const boost::property_tree::ptree & unitNode) :
    attacks_()
{
    using namespace boost::property_tree;

    Singular_           = unitNode.get<std::string>("singular");
    Plural_             = unitNode.get<std::string>("plural");

    MeshName_           = unitNode.get<std::string>("mesh.name");
    MeshYaw_            = unitNode.get<float>("mesh.yaw") / 180.0f * FLOAT_PI;
    MeshScale_          = unitNode.get<float>("mesh.scale");

    CollisionRadius_    = unitNode.get<WideInt>("stats.collision_radius");
    MaxSpeed_           = unitNode.get<WideInt>("stats.max_speed", 100);
    MaxTurnRate_        = unitNode.get<WideInt>("stats.max_turn_rate");
    MaxHealth_          = unitNode.get<WideInt>("stats.max_health");
    HealthRegenRate_    = unitNode.get<WideInt>("stats.health_regen_rate");
    MaxMorale_          = unitNode.get<WideInt>("stats.max_morale");
    MoraleRegenRate_    = unitNode.get<WideInt>("stats.morale_regen_rate");
    Persistence_        = unitNode.get<WideInt>("stats.persistence");


    const ptree & abilitiesNode = unitNode.get_child("abilities");
    for (ptree::const_iterator it = abilitiesNode.begin(), end = abilitiesNode.end(); it != end; ++it) {
        if (it->first == "attack") {
            attacks_.push_back(Attack(it->second));
        }
    }
}

UnitInvariants::UnitInvariants(const std::string & filename) :
    invariants_()
{
    using namespace boost::property_tree;

    ptree unitFile;
    read_info(filename, unitFile);

    for (ptree::const_iterator it = unitFile.begin(), end = unitFile.end(); it != end; ++it) {
        if (invariants_.find(it->first) != invariants_.end()) {
            throw Exception(0, "Unit invariant '" + it->first + "'duplicated", WHERE);
        }

        typedef std::pair<const std::string, UnitInvariant> Pair;
        invariants_.insert(Pair(it->first, UnitInvariant(it->second)));
    }
}

}; //sim
}; //spelprog2
